package org.egret.android_template;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;

import org.egret.egretnativeandroid.EgretNativeAndroid;
import org.egret.runtime.launcherInterface.INativePlayer;

import java.net.URI;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import gl.java.network.transport.kcp.core.UkcpChannel;
import gl.java.network.transport.kcp.umsp.UmspKcpClient;
import gl.java.umsp.Umsp;
import gl.java.umsp.UmspHeader;
import gl.java.umsp.client.UmspClientHandler;
import gl.java.util.ByteUtil;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;

//Android项目发布设置详见doc目录下的README_ANDROID.md

public class MainActivity extends Activity {
    private final String TAG = "MainActivity";
    private EgretNativeAndroid nativeAndroid;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getIntent().getData().toString();
        nativeAndroid = new EgretNativeAndroid(this);
        if (!nativeAndroid.checkGlEsVersion()) {
            Toast.makeText(this, "This device does not support OpenGL ES 2.0.",
                    Toast.LENGTH_LONG).show();
            return;
        }

        nativeAndroid.config.showFPS = true;
        nativeAndroid.config.fpsLogTime = 30;
        nativeAndroid.config.disableNativeRender = false;
        nativeAndroid.config.clearCache = false;
        nativeAndroid.config.loadingTimeout = 0;

        setExternalInterfaces();

        if (!nativeAndroid.initialize("http://192.168.8.102:5643/index.html")) {
            Toast.makeText(this, "Initialize native failed.",
                    Toast.LENGTH_LONG).show();
            return;
        }
        setContentView(nativeAndroid.getRootFrameLayout());


    }

    @Override
    protected void onPause() {
        super.onPause();
        nativeAndroid.pause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        nativeAndroid.resume();
    }

    @Override
    public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            nativeAndroid.exitGame();
        }

        return super.onKeyDown(keyCode, keyEvent);
    }

    private void setExternalInterfaces() {
        nativeAndroid.setExternalInterface("connectByUrl", new INativePlayer.INativeInterface() {
            @Override
            public void callback(final String message) {
                Log.i(TAG, "connectByUrl. " + message);
                new Thread() {
                    @Override
                    public void run() {
                        creatKcpClient(message);
                    }
                }.start();
            }
        });
        nativeAndroid.setExternalInterface("onWebSocketJSLoad", new INativePlayer.INativeInterface() {
            @Override
            public void callback(String message) {
                nativeAndroid.callExternalInterface("useNativeWebSocket", "egret");
                Log.i(TAG, "onWebSocketJSLoad, " + message);
            }
        });
        nativeAndroid.setExternalInterface("writeBytes", new INativePlayer.INativeInterface() {
            @Override
            public void callback(String message) {//this.socketID + "#" + dataView2Str(dataView, offset, len)
                sendKcpMessage(message);
            }
        });
    }

    private void sendKcpMessage(String message) {
        //this.socketID + "#" + dataView2Str(dataView, offset, len)
//        Log.i(TAG, "sendKcpMessage: " + message);
        String[] split = message.split("#");
        String id = split[0];
        if (!socketMap.containsKey(id)){
            Log.w(TAG, "sendKcpMessage: connection not exist");
            return;
        }
        String bytesString = split[1];
        byte[] bytea = ByteUtil.toByteArray(bytesString);
        Umsp.returnMsg(UmspHeader.fromByte(bytea),socketMap.get(id));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    private static String umsp2ByteStruing(UmspHeader uh) {
        return ByteUtil.toHexString(ByteBufUtil.getBytes(uh.toBytBuf()));
    }
    private static Map<String,Channel> socketMap = new ConcurrentHashMap();
    private void creatKcpClient(final String msg) {
        if (msg == null || !msg.contains("#")) {
            Log.i(TAG, "creatKcpClient: ill url formart,should like soucketID#xxx.com:8897,  not " + msg);
            return;
        }
        final String socketID = msg.split("#")[0];
        String s = msg.split("#")[1];
        URI uri = URI.create(s);
        final String host = uri.getHost();
        final int port = uri.getPort()-1;
        Log.i(TAG, (host + "," + port));
        UmspKcpClient.connect(host, port, new UmspClientHandler() {
            @Override
            protected void channelRead0(ChannelHandlerContext ctx, UmspHeader msg) throws Exception {
//                Log.i(TAG, "onMessage " + msg);
                String s1 = umsp2ByteStruing(msg);
                String s2 = socketID + "#SOCKET_DATA";
//                Log.i(TAG, "key: "+s2+",par:" + s1);
                nativeAndroid.callExternalInterface(s2, s1);
            }

            @Override
            public void channelActive(ChannelHandlerContext ctx) throws InterruptedException {
                Log.i(TAG, "onKcpConnect:" + ctx.channel() + " for " + socketID);
                ((UkcpChannel) ctx.channel()).channelID(Integer.parseInt(socketID));
                nativeAndroid.callExternalInterface(socketID + "#CONNECT", msg);
                socketMap.put(socketID,ctx.channel());
            }

            @Override
            public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                super.channelInactive(ctx);
                Log.i(TAG, "onDisConnect:" + ctx);
                nativeAndroid.callExternalInterface(socketID + "#CLOSE", "");
                socketMap.remove(socketID);
            }

            @Override
            public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                super.exceptionCaught(ctx, cause);
                nativeAndroid.callExternalInterface(socketID + "#IO_ERROR", cause.getMessage());
            }
        });
    }
}
